package cn.coco.jf.fw.api.dao;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.jfinal.kit.Kv;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.SqlPara;

import cn.coco.jf.fw.core.db.SysAccessTokenTbl;
import cn.coco.jf.fw.core.db.SysGenCodeTbl;
import cn.coco.jf.fw.core.db.SysItemTbl;
import cn.coco.jf.fw.core.db.SysOsEnvTbl;
import cn.coco.jf.fw.core.db.SysPropTbl;
import cn.coco.jf.fw.core.db.SysPtnVerbTbl;
import cn.coco.jf.fw.core.db.SysVerfCodeTbl;
import cn.exlu.coco.core.utils.DateUtil;
import cn.exlu.coco.core.utils.RandomUtil;
import cn.exlu.coco.core.utils.StringUtil;

public class SysDao {
    private static String SYNC_GEN_CODE ="genCode";
    private static String SYNC_GEN_VERF_CODE ="genVerfCode";
    
    private static String SYNC_GEN_ACCESST_OKEN ="genAccessToken";
    
    /**
     * 检索所有数据
     * @return
     */
    public static Map<String, String> queryAllSysPropTblMap(){
        SqlPara sqlPara = SysPropTbl.dao.getSqlPara("cn.coco.jf.sys.sql.queryAllSysPropTbl");
        List<SysPropTbl> list = SysPropTbl.dao.find(sqlPara);
        
        Map<String, String> map = new HashMap<String,String>();
        
        for(SysPropTbl entity : list){
            map.put(entity.getPropName(), entity.getPropValue());
        }
        
        return map;
    }

    public static String selectPropValue(String propName){
        Kv kv = Kv.by("propName", propName);
        SqlPara sqlPara = SysPropTbl.dao.getSqlPara("cn.coco.jf.sys.sql.selectPropValue", kv);
        SysPropTbl entity = SysPropTbl.dao.findFirst(sqlPara);
        
        if(entity == null){
            return null;
        }

        return entity.getPropValue();
    }
    
    public static List<SysPtnVerbTbl> querySysPtnVerTblByPtnType(String ptnType){
        Kv kv = Kv.by("ptnType", ptnType);
        SqlPara sqlPara = SysPtnVerbTbl.dao.getSqlPara("cn.coco.jf.sys.sql.querySysPtnVerTblByPtnType", kv);
        return SysPtnVerbTbl.dao.find(sqlPara);
    }
    
    public static List<SysItemTbl> querySysItemTblListByItemType(String itemType){
        Kv kv = Kv.by("itemType", itemType);
        SqlPara sqlPara = SysItemTbl.dao.getSqlPara("cn.coco.jf.sys.sql.querySysItemTblListByItemType", kv);
        return SysItemTbl.dao.find(sqlPara);
    }
    
    /**
     * 查询DB所有Access Token数据
     * @return
     */
    public static List<SysAccessTokenTbl> queryAllAccessToken(){
        SqlPara sqlPara = SysAccessTokenTbl.dao.getSqlPara("cn.coco.jf.sys.sql.queryAllAccessToken");
        return SysAccessTokenTbl.dao.find(sqlPara);
    }

    /**
     * 查询
     * @return
     */
    public static SysAccessTokenTbl selectSysAccessTokenTblByAccessToken(String accessToken){
        Kv kv = Kv.by("accessToken", accessToken);
        SqlPara sqlPara = SysAccessTokenTbl.dao.getSqlPara("cn.coco.jf.sys.sql.selectSysAccessTokenTblByAccessToken", kv);
        return SysAccessTokenTbl.dao.findFirst(sqlPara);
    }
    
    /**
     * 生成新的access token,并更新DB
     * @param appId
     * @return
     */
    public static SysAccessTokenTbl genAccessToken(String appId, int atLen){
        
        synchronized (SYNC_GEN_ACCESST_OKEN) {
            SysAccessTokenTbl entity = SysAccessTokenTbl.dao.findById(appId);
    
            String at = StringUtil.createRandomSalt(atLen);
    
            if (entity != null) {
                entity.setAccessTokenOld(entity.getAccessTokenNew());
                entity.setAccessTokenNew(at);
                entity.setGenDateTime(DateUtil.currentBusDate());
    
                entity.update();
    
                return entity;
            }
        
            entity = SysAccessTokenTbl.newInstance();
            entity.setAppId(appId);
            entity.setAccessTokenNew(at);
            entity.setGenDateTime(DateUtil.currentBusDate());

            entity.save();
            return entity;
        }

    }
    
    public static SysGenCodeTbl selectSysGenCodeTblBygenCode(String useDiv, String genCode, int expireInGen){
        Date nowDate = DateUtil.currentBusDate();
        
        Kv kv = Kv.by("useDiv", useDiv)
                .set("genCode", genCode);
        SqlPara sqlPara = SysGenCodeTbl.dao.getSqlPara("cn.coco.jf.sys.sql.querySysGenCodeTblByUseDivAndGenCode", kv);
        SysGenCodeTbl entity = SysGenCodeTbl.dao.findFirst(sqlPara);
        
        if(entity != null){
            // 判断有效期过期
            if((nowDate.getTime() - entity.getGenDateTime().getTime()) <= expireInGen){
                // 没有过期
                return entity;
            }
        }
        
        return null;
    }
    
    /**
     * 
     * @param useDiv
     * @param useIdf
     * @param bindContent
     * @param genCodeLen
     * @param expireInGen 生成的有效时长单位毫秒(如果为0，则每次都会重新生成)
     * @param expireInNoreapt 生成的保留时长单位毫秒(在保留时长内不能重复生成)
     * expireInNoreapt一定要大于expireInGen,且推荐 大于10 * 60 * 1000毫秒
     * @return
     */
    public static SysGenCodeTbl genCode(String useDiv, String useIdf, String bindContent, int genCodeLen, int expireInGen, int expireInNoreapt){
        synchronized (SYNC_GEN_CODE) {
            Date nowDate = DateUtil.currentBusDate();
            
            Kv kv = Kv.by("useDiv", useDiv)
                    .set("useIdf", useIdf);
            SqlPara sqlPara = SysGenCodeTbl.dao.getSqlPara("cn.coco.jf.sys.sql.querySysGenCodeTblByUseDivAndUseIdf", kv);
            SysGenCodeTbl entity = SysGenCodeTbl.dao.findFirst(sqlPara);
            
            if(entity != null){
                // 判断有效期过期
                if((nowDate.getTime() - entity.getGenDateTime().getTime()) <= expireInGen){
                    // 没有过期
                    return entity;
                }
            }
        
        
            // 获取有效code
            Kv kv2 = Kv.by("endDate", DateUtil.addMilliseconds(nowDate, -expireInNoreapt));
            SqlPara sqlPara2 = SysGenCodeTbl.dao.getSqlPara("cn.coco.jf.sys.sql.queryValidGenCodeListByEndDate", kv2);
            List<String> validGenCode = Db.query(sqlPara2.getSql(), sqlPara2.getPara());
            
            // 最大随机生成次数
            int maxGenTimes = 100;
            String tempCode = "";
            for(int i=0; i < maxGenTimes; i++){
                tempCode = RandomUtil.randomNum(genCodeLen);
                
                if(validGenCode.contains(tempCode)){
                    tempCode = "";
                    continue;
                }
            }
            
            if(StringUtil.isNullOrEmpty(tempCode)){
                return null;
            }
            
            if(entity != null){
                entity.setGenCode(tempCode);
                entity.setBindContent(bindContent);
                entity.setGenDateTime(nowDate);
                entity.update();
                return entity;
            }else{
                entity = SysGenCodeTbl.newInstance();
                entity.setUseDiv(useDiv);
                entity.setUseIdf(useIdf);
                entity.setGenCode(tempCode);
                entity.setBindContent(bindContent);
                entity.setGenDateTime(nowDate);
                entity.save();
                return entity;
            }
        }

    }

    public static String getEnvPropValue(String envValue, String propKey){
        SysOsEnvTbl sysOsEnvTbl = SysOsEnvTbl.dao.findByIds(envValue,propKey);

        if(sysOsEnvTbl != null){
            return sysOsEnvTbl.getPropValue();
        }

        return null;

    }

    /**
     * 
     * @param verfIdf
     * @param usageIdf
     * @param validSecs 有效时长（单位秒）
     * @param len 验证码长度（最大10位）
     * @return
     */
    public static String genVerfCode(String verfIdf, String usageIdf, int validSecs, int len){
        synchronized (SYNC_GEN_VERF_CODE) {
            SysVerfCodeTbl entity = SysVerfCodeTbl.dao.findByIds(verfIdf, usageIdf);
            Date curDate = DateUtil.currentBusDate();
            Date validDateTime = DateUtil.addMilliseconds(curDate, validSecs);
            if(entity == null){
                entity = SysVerfCodeTbl.newInstance();
                entity.setVerfIdf(verfIdf);
                entity.setUsageIdf(usageIdf);
                entity.setValidDateTime(validDateTime);
                entity.setVerfCode(StringUtil.createRandomNum(len));
                entity.save();
            }else{
                entity.setValidDateTime(validDateTime);
                entity.setVerfCode(StringUtil.createRandomNum(len));
                entity.update();
            }

            return entity.getVerfCode();
        }
    }

    /**
     * 
     * @param verfIdf
     * @param usageIdf
     * @param len
     * @return
     */
    public static SysVerfCodeTbl selectVerfCode(String verfIdf, String usageIdf){
        return SysVerfCodeTbl.dao.findByIds(verfIdf, usageIdf);
    }

    
}
